Before we start scripting the code that will progress our story, we need to set up the functionality
for a few more things.
One of those things is going to be our camera manipulation handler here on the client, and this is
going to be responsible for listening to events, for manipulating the position of the camera, changing
the occlusion mode of the camera, displaying jumpscares, and so on.
We have actually a total of four module scripts we need to set up for camera manipulation.
That being this handler, this jumpscares module script, the night vision module script.
And then we need to set up a new enum inside of replicated storage.
So we can go to the enums folder.
And what I'll do is I'll just duplicate one of these enums here.
And we're going to rename this to Camera Manipulation enum.
And we can go ahead and open that up as well.
So to get started we're going to go back into our camera manipulation handler.
And inside of our camera manipulation handler we're going to need a total of four services.
We're going to need to get replicated storage.
We're going to need the player service.
We will need the tween service.
And then we're going to need the sound service.
Now we can create the table that will represent this module script.
So we can just call it camera manipulation.
And we'll make sure to return that at the end of our module script.
And then we need a few more variables.
One we need a reference to our modules folder on the client.
So that's going to be equal to the script dot parent dot parent.
And then we get the modules folder.
We're going to make a reference to the player's current camera.
So that's in the workspace dot current camera.
We're going to get the local player player's dot local player.
We will need to refer to two different events.
One is a bindable event to allow local scripts to communicate with this handle, or to do different
camera manipulation stuff.
So we can call this manipulate cam Bindable and that's in replicated storage dot events, dot Bindable
dot manipulate camera.
And then we also need to refer to an event that the server can use to tell specific players to do different
camera stuff.
So we can call this manipulate cam event.
And that's in replicated storage dot events, dot remotes, dot manipulate camera.
Last but not least, we can go ahead and require our camera manipulation enum.
So require and replicated storage dot modules dot enums dot camera manipulation enum.
Now inside of this enum we can go ahead and delete these actions in here, because we're going to have
to replace these with different actions.
So in the client section we want to have the ability to, for example, move our camera to a specific
position or C frame.
So we can have this action be called move camera two.
We want to have the ability to reset the camera or basically make the camera go back to the player,
put it back in first person mode, and allow the player to have full control over the camera again.
So we can call this reset camera.
We want to have the ability to rotate our camera.
We want to have the ability to jump scare our player.
So when the server wants to jump scare a specific player, they'll fire that remote event and give us
the action of like a jump scare.
We want to have the ability to change the camera's occlusion mode.
Now, the default occlusion mode is the one that we all know where the player's camera collides with
objects, right?
We're not allowed to pass the player's camera through different objects, but there's other occlusion
modes where the camera is allowed to pass through different objects, and those objects can have their
transparency changed to see directly through them.
So when we're spectating other players, we want to be able to change the camera's occlusion mode to
see through different parts of the map.
So we can call this action set camera occlusion mode.
And then one more action we'll need is to be able to toggle night vision as well, because when we're
spectating, it's going to be pitch black and we're not going to be able to see anything unless we enable
for us to have night vision.
So we can see across the map.
So we can call this toggle night vision.
And then inside of the two server section.
The only action that we need to give to the server is to change the camera's occlusion, because unfortunately,
we can't change the camera's occlusion mode from the client side.
We actually have to tell the server to change it for the player.
So we'll have an action to give to the server and we'll call it change camera occlusion.
And this is going to be a server only action.
Now back inside of our camera manipulation handler we'll need a couple more variables.
One is we're going to require our jump scare module.
So that's going to be inside of our modules folder.
Camera manipulation dot jump scares.
And then we're also going to require our night vision module script.
So require modules dot camera manipulation dot night vision.
And we can go ahead and hop on those real quick.
We don't need to fill out jump scares for now, because we're going to be doing that later.
But we can quickly make the table to represent this module script.
So we'll just call it jump scares, and then we'll make sure to return that at the end here.
And then we could do the same thing for the night vision.
We'll make a variable called night vision and return that at the end of our script.
And then one last variable we'll need is a random data type.
Now some different private functions we're going to need is one.
We need a function to tween our camera to a specific position.
So this will get passed some tween data and a goal for the camera.
And we can use the tween service and create it on our current camera.
Do tween info.
Dot new.
And because, uh, we cannot pass tween information through remote events, then we're going to have
to, you know, ensure that we unpack all the stuff inside of this tween data table.
So we're going to use table dot unpack tween data.
And then we can pass our goal.
And then we could just play this tween.
We need a function to reset our camera.
And then we need a function to listen to our different, uh, binomial event and remote event.
So we can call this on cam manipulation event.
We'll get past an action and arguments to go with that action.
And then all we need for this handler is to have an initialize function.
So camera manipulation in it.
And the only purpose of this is to listen to when our cam Bindable event gets fired.
And we'll connect our on cam init event function.
And then we're going to do the same thing for the cam event dot on client event and connect on camera
manipulate event.
So inside of our on camera manipulation event function we need to listen to several different actions.
For example, if the action is equal to our camera manipulation enum dot two client dot move camera
to somewhere, then what we could do is we could set the current camera camera type equal to enum dot
camera TypeScript label.
Because we're only going to be able to tween and move the camera around when it's in its scriptable
state.
And then we can use our tween camera two function and pass the args dot tween data.
So uh, this table will contain a key for the tween data.
And then we can also have a key for the goal of the camera.
So we can just call it camera goal.
And our function will go ahead and take care of that for us.
Otherwise, if our action is equal to the camera manipulation enum dot two client dot.
Uh, let's say reset camera, then we can call our reset camera function and do that, and we'll fill
that out in a moment.
If the action is equal to camera manipulation enum dot two client dot.
Let's say rotate camera.
Then what we would do is we would also set the current camera camera type equal to the enum dot camera
type dot scriptable.
And then what we would do is we would use C frame angles to get a C frame with just a rotation.
So we can do C frame dot angles.
And we'll have another key pass to this function.
And we could call it something like args dot rotation.
So we could have a table containing the x, y and z rotation.
And we can unpack those values into our c frame dot angles.
And then now something very important to note is we want this action to define for us whether or not
we're just rotating the camera around some specific point, or we want the player's camera to rotate
around itself when it's in first person mode.
And this is very important because inside of a first person mode, uh, the player's camera is not directly
set into the center of the player's head.
It's actually offset behind the player's head just a little bit.
So we need to make sure that we account for that offset when we create the key frame that we want to
set the camera to, so we can create a variable called goal key frame.
And with this function inside of the arguments table, we can have a boolean like rotate around head.
And we could set that to true or false.
If it's true, then what we could do is we could set goal key frame equal to a new key frame.
And the position is going to be equal to the local player character dot head dot position.
So this is if our players in first person.
And then what we want to do is we want to subtract this position or offset it by the rotation dot look
vector.
So for example, if we wanted to rotate the camera around the player's head, the actual position of
the camera is like about one stud behind the head's position.
So we're getting the look vector and we're subtracting it by the head's position to get that offset
of about one stud behind the player's head.
That way, when we set the player's, uh, camera type back to be custom, it's not going to snap back
to the, uh, original camera position of our player when they're in first person.
That might not make sense, but trust me, it's important that we subtract our position by the look
vector of the rotation that we were past.
And then once we do that, we actually need to also apply the rotation on the key frame, because right
now we just have a key frame with a position but no rotation.
So we need to make sure we add our key frame dot angles as well.
So we'll add or basically multiply it by the rotation.
We're not actually multiplying.
This is just a symbol we're using to add this rotation to our key frame.
Now, if we don't need to rotate the camera around the player's head, then this will be a lot easier.
All we can do is just set goal keyframe equal to see frame dot new current camera dot keyframe dot position
and multiply it or add this rotation.
Then we can use our tween camera two function, and we can pass the tween data that gets passed to our,
uh, action.
And then we'll have a goal table which will be changing the see frame of our camera equal to this goal
keyframe.
Now the next action we can listen to in our camera manipulation enum.
Is, let's say we need to jump scare the player.
Well, this is when we would use our jump scare module and use a function in there to jump scare the
player, but we're not going to fill that out just yet.
So we're just going to leave this empty for now.
Another action we can listen to is let's say we need to, um, set the camera's occlusion mode to something
else.
So what we would do is we would get the enum that we need to set the occlusion mode to.
So we can have this args table contain a key that contains the occlusion mode for the camera.
And then we would take this occlusion mode and use our manipulation cam event and fire to the server
using the action of camera manipulation enum dot two server dot change camera occlusion.
And we could tell them that hey, we want to change it to this particular enum.
So we could do occlusion mode is equal to this enum.
Last but not least, the action we need to listen to right here is when we need to set the night vision
for our camera.
So that toggle night vision.
We would also use our night vision module script, and we could have a function in there like toggle.
And we could pass it a true or false boolean to either turn on or off the night vision.
So we could have another key inside of our args table, such as like we could call it set on.
And this will be the Boolean to tell us whether or not we need to turn on or off the night vision.
Now, before we fill out this function, let's go ahead and fill out our reset camera function first.
So inside of here, what we need to do is we want to move the player's camera back to the first person
position.
And instead of snapping the camera back to the first person position, I actually want to tween it there.
So we can create a tween using the tween service create on our current camera.
We could do a tween info of like 0.5 seconds.
And then we want to change the C frame of our camera, and we want to set it equal to a C frame.nu of
the local player, dot character, dot head dot position.
And again, because the first person position of the camera is slightly offset from the center of the
head, we need to subtract this by the current camera dot c frame dot look vector.
So this will put our camera as close as possible to the first person position.
And then we can also multiply this by the current cam dot c frame dot rotation.
So we'll move the player's camera back to their head so we can play this tween.
And then we'll wait for this tween to complete.
And then after it completes, we can set the local player dot camera max zoom distance equal to 0.5
and set the local player dot camera minimum zoom distance equal to 0.5 so they can't zoom out.
We can set the local player dot camera mode equal to the enum dot camera mode, dot lock, first person.
And just in case the occlusion mode of our camera is not the default occlusion mode, what we could
do is we could use our manipulate cam event and fire to the server.
So camera manipulation enum dot two server dot change camera occlusion.
We could pass a table with the occlusion mode, and that mode is going to be the default, which is
the enum.dev camera occlusion mode dot zoom.
After that, we can set the current cam dot camera type back to the enum dot camera type dot custom.
So it goes back to the first person mode.
And the default camera scripts have control again.
And then we can set the current cam dot camera subject equal to the local player.
Dot character.
Dot humanoid.
Okay.
Perfect.
Now we can go ahead and fill out the toggle function for our night vision.
So in order to achieve a night vision effect, we first need to tint the color of the player's screen
to be green.
And then we also want to change the ambient lighting in our game so the player can see farther away.
And the way we would do that is we would get the player's camera and we would add a color correction
effect.
And inside of here we could set the brightness to be like 0.2.
So we can increase the brightness on the screen.
We would want to increase the contrast as well.
We would want to set the saturation to something like negative one.
And then we would want to tint the color to a green color like we could do something.
Like this, and then afterwards we would also have to set the ambient inside of the lighting service
to a brighter color.
So if we do something like this, we're able to see farther across the map than if the ambient was at
the black state.
So as you can see, our night vision doesn't really work.
But if we increase the ambient now, it looks like our night vision is working.
So that means inside of our toggle function, we're going to have to add this color correction effect
and change the ambient in our lighting service.
So inside of here we can create a function for our night vision.
And it's going to be called toggle.
And we're going to get passed a boolean of whether or not we want to set this on or off.
We need to refer to our lighting service.
And then we're going to need a variable to refer to our current camera in the workspace.
So workspace dot current camera.
We want to have a boolean to keep track of whether or not our night vision is on.
So is night vision on.
We'll set that to false as default.
And then we need some constants.
One of these constants is going to be the lighting ambient original.
So what's the original ambient.
Well it's going to be equal to the lighting dot ambient.
And then we can have a lighting ambient bright.
And that's going to be color three from RGB.
And we could just basically bang this up all the way to the max.
So we get 255, 255, 255.
And then we also want to have a green color in here.
So that's going to be equal to color three from RGB.
We can go in here and get a green color.
So.
Make it slightly darker.
Something like that would probably work.
And then inside of our toggle function, we need to check if we want to set the night vision on or off.
So if set on and we want to make sure that our night vision isn't already on and not is night vision
on, what we could do is we could set is night vision on equal to true.
We're going to get a new color correction effect.
So color is equal to instance dot new color correction effect.
We're going to set the name of this color correction effect equal to night vision effect.
We can set the color dot brightness equal to like 0.2.
We'll set the color dot contrast equal to point two.
The color saturation is going to be equal to negative one.
The color tint color is going to be equal to our green color.
And then the parent.
Of this color correction effect is going to be inside of our current camera.
And then inside of the lighting service we can set the ambient equal to our lighting ambient bright.
So this will create that night vision effect for us.
And then if we want to disable our night vision so else if not set on.
Then what we could do is set is night vision on equal to false.
We'll check to see if the player has this color correction effect.
So current cam find first child.
And we're going to get the night vision effect.
So if they have this color correction effect, then we need to destroy it.
And then we need to set the lighting ambient Mac to the lighting ambient original.
Okay, I think that's all we need to do here.
Uh, we need to continue setting up, uh, some things before we can start our story.
So I'll go ahead and see you in the next lecture.